#pragma once
#ifndef PPU_H
#define PPU_H

////////////////////////////////////////////////////////////////////////////////////////////////////

#include "Commons.h"
#include <list>
// FIXME
#include <vector>

////////////////////////////////////////////////////////////////////////////////////////////////////

class PPU {
    public:
                            PPU             ();
        virtual             ~PPU            ();
        bool                WantNMI         ()const;
        void                ToggleNMI       ();
        unsigned char       ReadRegister    ( int );
        void                WriteRegister   ( int, unsigned char );
        void                RunScanline     ();
        bool                WantRender      ();
        void                WriteSpriteDMA  ( std::list<unsigned char> );

    // Setters
        void                SetReadVRAM     ( unsigned char (*value)(unsigned short) )          { m_ReadVRAM = value; }
        void                SetWriteVRAM    ( void (*value)(unsigned short, unsigned char) )    { m_WriteVRAM = value; }
        void                SetReadSRAM     ( unsigned char (*value)(unsigned char) )           { m_ReadSRAM = value; }
        void                SetWriteSRAM    ( void (*value)(unsigned char, unsigned char) )     { m_WriteSRAM = value; }
        void                SetMirroring    ( Mirroring value )                                 { m_Mirroring = value; }
        
    // Getters
        unsigned long*      GetScreenData   ()                                                  { return m_ScreenData; }

    private:
        unsigned char               Read2002            ();
        unsigned char               Read2004            ();
        unsigned char               Read2007            ();
        void                        Write2000           ( unsigned char );
        void                        Write2003           ( unsigned char );
        void                        Write2004           ( unsigned char );
        void                        Write2005           ( unsigned char );
        void                        Write2006           ( unsigned char );
        void                        Write2007           ( unsigned char );
        void                        RaiseInterrupt      ( Interrupt );
        void                        DrawBackground      ();
        void                        DrawSprites         ( bool );

        PPU_REGISTERS               m_Reg;
        unsigned char               m_Bus;
        unsigned char               m_Buffer;
        bool                        m_Latch;
        int                         m_Scanline;
        bool                        m_VBlank;
        bool                        m_SpriteOverflow;
        bool                        m_NMI;
        Mirroring                   m_Mirroring;
        unsigned char               ( *m_ReadVRAM )     ( unsigned short );
        void                        ( *m_WriteVRAM )    ( unsigned short, unsigned char );
        unsigned char               ( *m_ReadSRAM )     ( unsigned char );
        void                        ( *m_WriteSRAM )    ( unsigned char, unsigned char );
        bool                        m_CanRender;
        unsigned short              m_LoopyT;
        unsigned long*              m_ScreenData;
};

////////////////////////////////////////////////////////////////////////////////////////////////////

#endif

////////////////////////////////////////////////////////////////////////////////////////////////////
